import time

from flask import Flask, render_template, request,session,redirect,jsonify
import json
from . import recalltest
import os
from frameworks.cores.Config import *
from frameworks.utils.JsonResult2 import *
from frameworks.cores.LoadClass import *
import datetime
from dateutil.relativedelta import relativedelta
import akshare as ak
from flask import Flask, render_template
from pyecharts.charts import Line
from pyecharts import options as opts
import pandas as pd
import sqlite3
import re
import sqlite3
import datetime
import numpy as np
import random
import pandas as pd
import matplotlib.pyplot as plt
from mpl_finance import candlestick_ohlc
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.dates import DateFormatter, MonthLocator

mpl.rcParams['font.sans-serif'] = ['SimHei']  # 指定默认字体
mpl.rcParams['axes.unicode_minus'] = False  # 解决保存图像是负号'-'显示为方块的问题
import datetime

basepath = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))))
config = Config(basepath)

apimap = config.getApi()
env = apimap["base"]
print(env)
from flask_session import Session

jsonResult = JsonResult2()

loader = LoadClass()

import datetime
import time

# 初始化数据库
# 初始化数据库
# 初始化数据库
def init_db():
    conn = sqlite3.connect('trades.db')
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS trades
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                 stock TEXT NOT NULL,
                 quantity INTEGER NOT NULL,
                 price REAL NOT NULL,
                 type TEXT NOT NULL,
                 timestamp TEXT NOT NULL)''')
    c.execute('''CREATE TABLE IF NOT EXISTS backtest_trades
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                 stock TEXT NOT NULL,
                 quantity INTEGER NOT NULL,
                 price REAL NOT NULL,
                 type TEXT NOT NULL,
                 timestamp TEXT NOT NULL,
                 backtest_start TEXT NOT NULL,
                 backtest_end TEXT NOT NULL)''')
    conn.commit()
    conn.close()

def get_data_no_index(code, start_day, end_day):
    stock_data = pd.read_csv('D:\\csv_shares_day\\' + str(code) + '-19900101-20211231.csv', encoding="gbk")
    stock_data.columns = ["Date", "code", "name", "close", "high", "low", "open", "pre_close", "subval",
                          "subrate",
                          "turnrate",
                          "volume", "money", "all_earn", "exchage_earn"]
    stock_data["trading_date"] = stock_data["Date"]
    stock_data.set_index(['trading_date'], inplace=True)
    dfall = stock_data.sort_values(by=["trading_date"])
    dfall['Date'] = list(
        map(lambda x: mdates.date2num(datetime.datetime.strptime(x, '%Y-%m-%d')), dfall.index.tolist()))
    dfall['ma3'] = dfall["close"].rolling(3).mean()
    dfall['ma5'] = dfall["close"].rolling(5).mean()
    dfall['ma10'] = dfall["close"].rolling(10).mean()
    dfall['ma18'] = dfall["close"].rolling(18).mean()
    dfall['ma30'] = dfall["close"].rolling(30).mean()
    date = datetime.datetime.strptime(start_day, '%Y-%m-%d')
    # 计算半年后的日期
    half_year_later = date + relativedelta(months=6)
    # 将结果转换为字符串
    calc_day = half_year_later.strftime('%Y-%m-%d')
    dfall = dfall.loc[calc_day:end_day]
    return dfall


# 计算 5 日线
def calculate_five_day_ma(prices):
    if len(prices) < 5:
        return None
    return np.mean(prices[-5:])


# 回溯测试，包含自动交易逻辑
@recalltest.route('/backtest', methods=['GET'])
def backtest():
    stock = request.args.get('stock')
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')

    if not stock or not start_date or not end_date:
        return jsonify({'code': 1, 'msg': '缺少必要参数'})

    data = get_data_no_index(stock,start_date,end_date)

    if len(data) < 2:
        return jsonify({'code': 1, 'msg': '交易记录不足，无法进行回溯测试'})

    # 简单的回溯策略：根据 5 日线决定交易
    initial_cash = 100000
    cash = initial_cash
    shares = 0
    backtest_trades = []
    profit_list = [initial_cash]
    prices = []

    for index, row in data.iterrows():
        price = row["close"]
        timestamp = index
        prices.append(price)
        ma_5 = round(row["ma5"], 2)

        if ma_5 is None:
            continue

        current_price = price
        if current_price > ma_5 and shares == 0:
            # 买入
            shares_to_buy = cash // current_price
            cash -= shares_to_buy * current_price
            shares += shares_to_buy
            backtest_trades.append({
                'timestamp': timestamp,
                'type': '买入',
                'quantity': shares_to_buy,
                'price': current_price
            })

            # 存储回溯交易记录
            conn = sqlite3.connect('trades.db')
            c = conn.cursor()
            c.execute("INSERT INTO backtest_trades (stock, quantity, price, type, timestamp, backtest_start, backtest_end) VALUES (?,?,?,?,?,?,?)",
                      (stock, shares_to_buy, current_price, '买入', timestamp, start_date, end_date))
            conn.commit()
            conn.close()
        elif current_price < ma_5 and shares > 0:
            # 卖出
            cash += shares * current_price
            backtest_trades.append({
                'timestamp': timestamp,
                'type': '卖出',
                'quantity': shares,
                'price': current_price
            })
            # 存储回溯交易记录
            conn = sqlite3.connect('trades.db')
            c = conn.cursor()
            c.execute("INSERT INTO backtest_trades (stock, quantity, price, type, timestamp, backtest_start, backtest_end) VALUES (?,?,?,?,?,?,?)",
                      (stock, shares, current_price, '卖出', timestamp, start_date, end_date))
            conn.commit()
            conn.close()
            shares = 0

        current_value = round(cash + shares * current_price, 2)
        profit_list.append(current_value)

    final_value = cash + shares * data.iloc[-1:]["close"]
    profit = final_value - initial_cash

    return jsonify({'code': 0, 'msg': '成功', 'backtest_trades': backtest_trades, 'profit': profit, 'profit_list': profit_list})


def getProfitList(stock,start_date,end_date):
    if not stock or not start_date or not end_date:
        return jsonify({'code': 1, 'msg': '缺少必要参数'})

    data = get_data_no_index(stock, start_date, end_date)

    if len(data) < 2:
        return jsonify({'code': 1, 'msg': '交易记录不足，无法进行回溯测试'})

    # 简单的回溯策略：根据 5 日线决定交易
    initial_cash = 100000
    cash = initial_cash
    shares = 0
    profit_list = [initial_cash]
    prices = []
    date_list = []

    for index, row in data.iterrows():
        price = row["close"]
        prices.append(price)
        ma_5 = round(row["ma5"], 2)

        if ma_5 is None:
            continue

        current_price = price
        if current_price > ma_5 and shares == 0:
            # 买入
            shares_to_buy = cash // current_price
            cash -= shares_to_buy * current_price
            shares += shares_to_buy
        elif current_price < ma_5 and shares > 0:
            # 卖出
            cash += shares * current_price
            shares = 0

        current_value = round(cash + shares * current_price, 2)
        profit_list.append(current_value)
        date_list.append(index)

    final_value = cash + shares * data.iloc[-1:]["close"]
    profit = final_value - initial_cash

    return {'code': 0, 'msg': '成功', 'profit': profit,'date_list':date_list,'profit_list': profit_list}

# 获取回溯交易列表
@recalltest.route('/get_backtest_list', methods=['GET'])
def get_backtest_list():
    conn = sqlite3.connect('trades.db')
    c = conn.cursor()
    c.execute("SELECT DISTINCT stock, backtest_start, backtest_end FROM backtest_trades")
    backtest_list = c.fetchall()
    conn.close()

    result = []
    for item in backtest_list:
        result.append({
            'stock': item[0],
            'backtest_start': item[1],
            'backtest_end': item[2]
        })

    return jsonify({'code': 0, 'msg': '成功', 'data': result})


# 获取指定回溯交易的详细记录
@recalltest.route('/get_backtest_records', methods=['GET'])
def get_backtest_records():
    stock = request.args.get('stock')
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')

    if not stock or not start_date or not end_date:
        return jsonify({'code': 1, 'msg': '缺少必要参数'})

    conn = sqlite3.connect('trades.db')
    c = conn.cursor()
    c.execute("SELECT * FROM backtest_trades WHERE stock =? AND backtest_start =? AND backtest_end =?",
              (stock, start_date, end_date))
    trades = c.fetchall()
    conn.close()

    trade_list = []
    for trade in trades:
        trade_dict = {
            'id': trade[0],
            'stock': trade[1],
            'quantity': trade[2],
            'price': trade[3],
            'type': trade[4],
            'timestamp': trade[5],
            'backtest_start': trade[6],
            'backtest_end': trade[7]
        }
        trade_list.append(trade_dict)

    # 假设我们在这里也返回 profit_list，需要调整后端逻辑来计算它
    # 这里简单假设已经有一个计算 profit_list 的函数 calculate_profit_list
    profitObj = getProfitList(stock,start_date, end_date)
    return jsonify({'code': 0, 'msg': '成功', 'data': trade_list, 'date_list':profitObj["date_list"], 'profit_list': profitObj["profit_list"]})

# 首页
@recalltest.route('/generate')
def index():
    #init_db()
    return render_template('recalltest/generate.html')

# 交易记录页面路由
@recalltest.route('/trade_records')
def trade_records():
    stock = request.args.get('stock')
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')
    return render_template('recalltest/trade_records.html', stock=stock, start_date=start_date, end_date=end_date)


# 收益折线图页面路由
@recalltest.route('/profit_chart')
def profit_chart():
    stock = request.args.get('stock')
    start_date = request.args.get('start_date')
    end_date = request.args.get('end_date')
    return render_template('recalltest/profit_chart.html', stock=stock, start_date=start_date, end_date=end_date)

